// 1.插件：挂载$store
// 2.实现Store

let Vue;

class Store {
  constructor(options) {
      const store = this;
      this._mutations = options.mutations;
      this._actions = options.actions;
      store._wrappedGetters = options.getters;
      this.getters = {};
      const computed = {};

      // defineProperty(this.getters, 'doubleCounter', {get(){}})
      // 最后还能利用vue计算属性来做响应式处理
      Object.keys(store._wrappedGetters).forEach(key => {
          computed[key] = function () {
              return store._wrappedGetters[key](store.state);
          };
          Object.defineProperty(store.getters,key,{
              get:() => store._vm[key]
            });
      });
      // data响应式处理
      // this.$store.state.xx
      this._vm = new Vue({
          data: {
              $$state: options.state
          },
          computed //// 利用vue计算属性来做响应式处理
      })



      //diapach-->执行actions-->actions可能里面异步函数，这样的话很难保证在执行的时候this的值，因此要对
      // actions进行绑定this
      // commits也是同理
      this.commit = this.commit.bind(this)
      this.dispatch = this.dispatch.bind(this)

  }

  get state() {
    return this._vm._data.$$state
  }

  set state(v) {
    console.error('please use replaceState to reset state');
    
  }
  
  commit(type, payload) {
    const entry = this._mutations[type]
    if (!entry) {
      console.error('unkown mutation type');
    }

    entry(this.state, payload)
  }
  
  dispatch(type, payload) {
    const entry = this._actions[type]
    if (!entry) {
      console.error('unkown action type');
    }

    entry(this, payload)
  }
  
}

// Vue.use
// install.apply(this, [this,...])
function install(_Vue) {
  Vue = _Vue

  Vue.mixin({
    beforeCreate() {
      if (this.$options.store) {
        Vue.prototype.$store = this.$options.store
      }
    }
  })
}

export default { Store, install };
